﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CorreoSocialWeb.Models
{
    public class RutaDeEnvioBusqueda
    {
        public Envio Envio { get; private set; }
        public Ruta Ruta { get; private set; }

        public int EnvioId
        {
            get
            {
                return this.Envio.Id;
            }
        }

        public int RutaId
        {
            get
            {
                return Ruta.Id;
            }
        }

        public string Notas
        {
            get
            {
                return this.Ruta.Notas;
            }
        }

        public Usuario Mensajero
        {
            get
            {
                return this.Ruta.Usuario;
            }
        }

        public string OrigenDestinoString
        {
            get
            {
                return this.Ruta.OrigenDestinoString;
            }
        }

        public bool Cumple
        {
            get
            {
                return this.CumpleDiaDeLaSemana 
                            && this.CumpleTamano
                            && this.DistanciaTotal < 5;
            }
        }

        public RutaDeEnvioBusqueda(RutaDeEnvio rutaDeEnvio) : this(rutaDeEnvio.Envio, rutaDeEnvio.Ruta)
        { 
        }

        public RutaDeEnvioBusqueda(Envio envio, Ruta ruta)
        {
            this.Ruta = ruta;
            this.Envio = envio;
        }

        public double DistanciaTotal
        {
            get
            {
                return this.DistanciaAOrigen + this.DistanciaADestino;
            }
        }

        private string DistanciaString(double valor)
        {
            double val = (float)System.Math.Round(valor, 2);

            if (val < 0.1)
                return string.Format("{0:f2} {1}", valor * 100, "m");
            else if (val < 1)
                return string.Format("{0:f2} {1}", valor * 10, "cuadras");
            else
                return string.Format("{0:f2} {1}", valor, "km");
        }

        public string DistanciaTotalString
        {
            get
            {
                return string.Format("{0:f2} ({1:f2}+{2:f2})"
                    , DistanciaString(this.DistanciaAOrigen + this.DistanciaADestino)
                    , DistanciaString(this.DistanciaAOrigen)
                    , DistanciaString(this.DistanciaADestino)
                    );
            }
        }

        public bool CumpleDiaDeLaSemana
        {
            get
            {
                if (this.Ruta.DiasDisponiblesEnu == DisponibilidadDias.Ninguno)
                    return false;

                if (!this.Envio.FechaDeSalida.HasValue)
                    return true;

                return true;

                //return this.Ruta.AdmiteDia(this.Envio.FechaDeSalida.Value);
            }
        }

        public int MinutosDeEsperaSalida
        {
            get
            {
                if (!this.Envio.HorarioDeSalida.HasValue)
                    return 0;

                int minutosRuta = (this.Ruta.HorarioDeSalida / 100) * 60 + (this.Ruta.HorarioDeSalida % 100);
                int minutosEnvio = (this.Envio.HorarioDeSalida.Value / 100) * 60 + (this.Envio.HorarioDeSalida.Value % 100);

                return System.Math.Abs(minutosRuta - minutosEnvio);
            }
        }

        public string MinutosDeEsperaTotalString
        {
            get
            {
                if (this.MinutosDeEsperaTotal.Equals(0))
                    return "(sin espera)";

                var texto = string.Empty;

                if (this.MinutosDeEsperaTotal >= 60)
                    texto = string.Format("{0} hora(s)", this.MinutosDeEsperaTotal / 60);

                if ((this.MinutosDeEsperaTotal % 60) != 0)
                    texto += string.Format(" {0:d2} minutos", this.MinutosDeEsperaTotal % 60);

                return texto.Trim();
            }
        }

        public int MinutosDeEsperaTotal
        {
            get
            {
                return (this.MinutosDeEsperaSalida + this.MinutosDeEsperaLlegada);
            }
        }

        public int MinutosDeEsperaLlegada
        {
            get
            {
                if (!this.Envio.HorarioDeLlegada.HasValue)
                    return 0;

                int minutosRuta = (this.Ruta.HorarioDeLlegada / 100) * 60 + (this.Ruta.HorarioDeLlegada % 100);
                int minutosEnvio = (this.Envio.HorarioDeLlegada.Value / 100) * 60 + (this.Envio.HorarioDeLlegada.Value % 100);

                return System.Math.Abs(minutosRuta - minutosEnvio);
            }
        }

        public int DiasDeEspera
        {
            get
            {
                if (this.Ruta.DiasDisponiblesEnu == DisponibilidadDias.Ninguno)
                    return 999999;

                if (!this.Envio.FechaDeSalida.HasValue)
                    return 0;

                var fecha = this.Envio.FechaDeSalida.Value;
                var count = 0;

                while (!Ruta.AdmiteDia(fecha))
                {
                    fecha = fecha.AddDays(1);
                    count++;
                }

                return count;
            }
        }

        public bool CumpleTamano
        {
            get
            {
                if (Ruta.TamanoDePaquete == null)
                    return false;

                if (Envio.TamanoDePaquete == null)
                    return false;

                return this.Ruta.TamanoDePaquete.EsMasGrandeQue(this.Envio.TamanoDePaquete);
            }
        }

        public double DistanciaAOrigen
        {
            get
            {
                return DistanciaLatLong.Get(Ruta.OrigenLatitud, Ruta.OrigenLongitud
                    , Envio.OrigenLatitud, Envio.OrigenLongitud) / 1000;
            }
        }

        public double DistanciaADestino
        {
            get
            {
                return DistanciaLatLong.Get(Ruta.DestinoLatitud, Ruta.DestinoLongitud
                    , Envio.DestinoLatitud, Envio.DestinoLongitud) / 1000;
            }
        }

        public int Ranking { get; private set; }

        public void SetRanking(int valor)
        {
            this.Ranking = valor;
        }

        public string DiasDeEsperaString
        {
            get
            {
                if (this.DiasDeEspera.Equals(0))
                    return "(sin espera)";

                return this.DiasDeEspera.ToString();

                //if (this.DiasDeEspera < 7)
                //    return string.Format("{0} {1}", this.DiasDeEspera, "días");
            }
        }

        public double RankingDouble
        {
            get
            {
                double suma = 0;

                suma += this.DistanciaTotal * (double)1000 * (double)1000;

                suma += this.DiasDeEspera * 1000;

                suma += this.MinutosDeEsperaTotal;

                return suma;
            }
        }
    }
}